package com.zhao.dota.security.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;

public class LoginFilter extends UsernamePasswordAuthenticationFilter {

    private ThreadLocal<Map<String, String>> paramsThreadLocal = ThreadLocal.withInitial(HashMap::new);

    @Autowired
    public LoginFilter(AuthenticationManager authManager) {
        super();
        setAuthenticationManager(authManager);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        initParams(request);
        Authentication authentication = super.attemptAuthentication(request, response);
        paramsThreadLocal.remove();
        return authentication;
    }

    @Override
    protected String obtainPassword(HttpServletRequest request) {
        return getParams(SPRING_SECURITY_FORM_PASSWORD_KEY);
    }

    @Override
    protected String obtainUsername(HttpServletRequest request) {
        return getParams(SPRING_SECURITY_FORM_USERNAME_KEY);
    }

    private void parseJsonParams(HttpServletRequest request) {
        Map<String, String> paramsMap = paramsThreadLocal.get();
        StringBuilder sb = new StringBuilder();
        JSONObject jsonObject;
        try (ServletInputStream inputStream = request.getInputStream();
             BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")))) {
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
            String s = sb.toString();
            jsonObject = JSON.parseObject(s);
        } catch (IOException e) {
            throw new AuthenticationServiceException("", e);
        }
        for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            paramsMap.put(key, value.toString().trim());
        }
    }

    private void parseNormalParams(HttpServletRequest request) {
        Map<String, String> paramsMap = paramsThreadLocal.get();
        // 解析请求body
        Map<String, String[]> parameterMap = request.getParameterMap();
        for (String key : parameterMap.keySet()) {
            String[] strings = parameterMap.get(key);
            if (strings != null && strings.length > 0) {
                paramsMap.put(key, strings[0].trim());
            }
        }
    }

    private void initParams(HttpServletRequest request) {
        String contentType = request.getContentType();
        if (contentType != null && contentType.toUpperCase().contains("application/json".toUpperCase())) {
            parseJsonParams(request);
        } else {
            parseNormalParams(request);
        }
    }

    private String getParams(String name) {
        return paramsThreadLocal.get().get(name);
    }

}
